package com.unicloud.medical.oss.common.util;

import com.google.protobuf.ByteString;
import com.unicloud.medical.oss.common.enums.ErrorEnum;
import com.unicloud.medical.oss.common.model.BucketInfo;
import com.unicloud.medical.oss.common.model.DownloadObject;
import com.unicloud.medical.oss.common.model.ObjectInfo;
import com.unicloud.medical.oss.service.grpc.*;
import com.unisound.medical.common.exception.BusinessException;
import com.unisound.medical.common.exception.ExceptionMessage;
import com.unisound.medical.common.model.dto.ResultDTO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Slf4j
public class GrpcResultDTOUtil {

    public static GrpcResultDTO toGrpc(ResultDTO<Boolean> resultDTO) {
        GrpcResultDTO.Builder builder = GrpcResultDTO.newBuilder();
        if (StringUtils.isNotEmpty(resultDTO.getCode())) {
            builder.setCode(resultDTO.getCode());
        }
        if (StringUtils.isNotEmpty(resultDTO.getMessage())) {
            builder.setMessage(resultDTO.getMessage());
        }
        builder.setSuccess(resultDTO.isSuccess());
        if (Objects.nonNull(resultDTO.getData())) {
            builder.setData(resultDTO.getData());
        }

        return builder.build();
    }

    public static ExceptionMessage errorMessage(Exception e) {
        if (e instanceof BusinessException) {
            return ((BusinessException) e).getExceptionMessage();
        }

        log.error("errorMessage. cause={}", e);
        ErrorEnum errorEnum = ErrorEnum.SYSTEM_ERROR;
        return new ExceptionMessage(errorEnum.getErrCode(), errorEnum.getErrMsg());
    }

    public static GrpcResultDTOV2 successV2(ResultDTO<String> resultDTO) {
        GrpcResultDTOV2.Builder builder = GrpcResultDTOV2.newBuilder();
        if (StringUtils.isNotEmpty(resultDTO.getCode())) {
            builder.setCode(resultDTO.getCode());
        }
        if (StringUtils.isNotEmpty(resultDTO.getMessage())) {
            builder.setMessage(resultDTO.getMessage());
        }
        builder.setSuccess(resultDTO.isSuccess());
        if (Objects.nonNull(resultDTO.getData())) {
            builder.setData(resultDTO.getData());
        }
        return builder.build();
    }

    public static GrpcResultDTOV2 failV2(Exception e) {
        return failV2(errorMessage(e));
    }

    public static GrpcResultDTOV2 failV2(ExceptionMessage exceptionMessage) {
        return GrpcResultDTOV2.newBuilder()
                .setSuccess(false)
                .setCode(exceptionMessage.getErrorCode())
                .setMessage(exceptionMessage.getErrorMessage())
                .build();
    }

    public static GrpcResultDTOV3 successV3(ResultDTO<List<String>> resultDTO) {
        GrpcResultDTOV3.Builder builder = GrpcResultDTOV3.newBuilder();
        if (StringUtils.isNotEmpty(resultDTO.getCode())) {
            builder.setCode(resultDTO.getCode());
        }
        if (StringUtils.isNotEmpty(resultDTO.getMessage())) {
            builder.setMessage(resultDTO.getMessage());
        }
        builder.setSuccess(resultDTO.isSuccess());
        if (CollectionUtils.isNotEmpty(resultDTO.getData())) {
            builder.addAllData(resultDTO.getData());
        }
        return builder.build();
    }

    public static GrpcResultDTOV3 failV3(Exception e) {
        return failV3(errorMessage(e));
    }

    public static GrpcResultDTOV3 failV3(ExceptionMessage exceptionMessage) {
        return GrpcResultDTOV3.newBuilder()
                .setSuccess(false)
                .setCode(exceptionMessage.getErrorCode())
                .setMessage(exceptionMessage.getErrorMessage())
                .build();
    }

    public static GrpcResultDTOV4 successV4(ResultDTO<List<ObjectInfo>> resultDTO) {
        GrpcResultDTOV4.Builder builder = GrpcResultDTOV4.newBuilder();
        if (StringUtils.isNotEmpty(resultDTO.getCode())) {
            builder.setCode(resultDTO.getCode());
        }
        if (StringUtils.isNotEmpty(resultDTO.getMessage())) {
            builder.setMessage(resultDTO.getMessage());
        }
        builder.setSuccess(resultDTO.isSuccess());

        List<ObjectInfo> dataList = resultDTO.getData();
        if (CollectionUtils.isNotEmpty(dataList)) {
            builder.addAllData(dataList.stream()
                    .map(objectInfo -> GrpcObjectInfo.newBuilder()
                            .setName(objectInfo.getName())
                            .setSize(objectInfo.getSize())
                            .build())
                    .collect(Collectors.toList()));
        }
        return builder.build();
    }

    public static GrpcResultDTOV5 successV5(ResultDTO<List<BucketInfo>> resultDTO) {
        GrpcResultDTOV5.Builder builder = GrpcResultDTOV5.newBuilder();
        if (StringUtils.isNotEmpty(resultDTO.getCode())) {
            builder.setCode(resultDTO.getCode());
        }
        if (StringUtils.isNotEmpty(resultDTO.getMessage())) {
            builder.setMessage(resultDTO.getMessage());
        }
        builder.setSuccess(resultDTO.isSuccess());

        List<BucketInfo> dataList = resultDTO.getData();
        if (CollectionUtils.isNotEmpty(dataList)) {
            builder.addAllData(dataList.stream()
                    .map(bucketInfo -> GrpcBucketInfo.newBuilder()
                            .setName(bucketInfo.getName())
                            .setCreateDate(bucketInfo.getCreateDate())
                            .build())
                    .collect(Collectors.toList()));
        }
        return builder.build();
    }

    public static GrpcResultDTOV5 failV5(ExceptionMessage exceptionMessage) {
        return GrpcResultDTOV5.newBuilder()
                .setSuccess(false)
                .setCode(exceptionMessage.getErrorCode())
                .setMessage(exceptionMessage.getErrorMessage())
                .build();
    }

    public static GrpcResultDTOV6 successV6(ResultDTO<DownloadObject> resultDTO) {
        GrpcResultDTOV6.Builder builder = GrpcResultDTOV6.newBuilder();
        if (StringUtils.isNotEmpty(resultDTO.getCode())) {
            builder.setCode(resultDTO.getCode());
        }
        if (StringUtils.isNotEmpty(resultDTO.getMessage())) {
            builder.setMessage(resultDTO.getMessage());
        }
        builder.setSuccess(resultDTO.isSuccess());

        DownloadObject data = resultDTO.getData();
        if (data != null) {
            builder.setData(GrpcDownloadObject.newBuilder()
                    .setContentType(data.getContentType())
                    .setFileName(data.getFileName())
                    .setData(ByteString.copyFrom(data.getData()))
                    .build());
        }
        return builder.build();
    }

    public static GrpcResultDTOV6 failV6(ExceptionMessage exceptionMessage) {
        return GrpcResultDTOV6.newBuilder()
                .setSuccess(false)
                .setCode(exceptionMessage.getErrorCode())
                .setMessage(exceptionMessage.getErrorMessage())
                .build();
    }

    public static GrpcResultDTOV6 failV6(Exception e) {
        return failV6(errorMessage(e));
    }

}
